package com.bailan.foreat.controller;


import com.bailan.foreat.entity.User;
import com.bailan.foreat.service.UserService;
import com.bailan.foreat.utils.CookieUtils;
import com.bailan.foreat.utils.JwtUtils;
import com.bailan.foreat.utils.UserUtils;
import com.google.code.kaptcha.Producer;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author ste
 * @since 2023-02-21 07:50:44
 */
@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    Producer producer;

    @Autowired
    UserService userService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    JavaMailSender javaMailSender;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    UserController userController;

    @RequestMapping("getKaptchaImage")
    public void getKaptchaImage(HttpServletResponse response, HttpSession httpSession) throws IOException {
        //生成验证码
        String codeText = producer.createText();
//        codeText = "0000"; //手动指定验证码,方便调试
        httpSession.setAttribute("kaptchaCode", codeText);

        BufferedImage codeImage = producer.createImage(codeText);

        response.setContentType("image/png");
        ImageIO.write(codeImage, "png", response.getOutputStream());

    }


    @PostMapping("login")
    public String login(String username, String password, String code,
                        HttpSession httpSession, Model model, HttpServletResponse response) {

        //校验验证码
        String kaptchaCode = (String) httpSession.getAttribute("kaptchaCode");
        if (StringUtils.isEmpty(code) || !code.equals(kaptchaCode)) {
            model.addAttribute("errorInfo", "验证码错误");
            return "userlogin";
        }

        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            model.addAttribute("errorInfo", "用户名或密码错误");
            return "userlogin";
        }

        User userByAccount = userService.getUserByUsername(username);
        if (null == userByAccount || !password.equals(userByAccount.getPassword())) {
            model.addAttribute("errorInfo", "用户名或密码错误");
            return "userlogin";
        }

        //登录成功
        String token = JwtUtils.createToken(userByAccount.getUsername(), 20);
        CookieUtils.setUserToken2Cookie(response, token);

        //在redis里也保存一份信息,有效期30分钟
        stringRedisTemplate.opsForValue().set(token, userByAccount.getUsername(), 30, TimeUnit.MINUTES);

        //跳转到用户端app主页
        return "redirect:/";
    }

    @RequestMapping("reLog")
    @ResponseBody
    public void reLog(HttpServletResponse response, HttpServletRequest request, String username) {
        //变更了username
        //先注销
        userController.logout(response, request);
        //再自动登录
        String token = JwtUtils.createToken(username, 20);
        CookieUtils.setUserToken2Cookie(response, token);

        //在redis里保存信息,有效期30分钟
        stringRedisTemplate.opsForValue().set(token, username, 30, TimeUnit.MINUTES);
    }

    @RequestMapping("currentAccount")
    @ResponseBody
    public String currentAccount(HttpServletRequest request) {
        String account = "";

        String userTokenFromCookie = CookieUtils.getUserTokenFromCookie(request);
        String currentAccount = JwtUtils.getAccountWithoutException(userTokenFromCookie);
        account = StringUtils.isEmpty(currentAccount) ? account : currentAccount;

        return account;
    }

    @RequestMapping("currentUser")
    @ResponseBody
    public User currentUser(HttpServletRequest request) {
        User currentUser = UserUtils.getCurrentUser(request);

        return currentUser;
    }

    @RequestMapping("logout")
    public void logout(HttpServletResponse response, HttpServletRequest request) {
        CookieUtils.deleteUserTokenFromCookie(response);

        //同时删除redis中的信息
        String userTokenFromCookie = CookieUtils.getUserTokenFromCookie(request);
        if (!StringUtils.isEmpty(userTokenFromCookie)) {
            stringRedisTemplate.delete(userTokenFromCookie);
        }
    }

    @RequestMapping("getEmailCode")
    @ResponseBody
    public String getEmailCode(String email) {

        //正则表达式校验邮箱
        String regex = "^(.+)@(.+)$";
        Pattern pattern = Pattern.compile(regex);
        boolean isOK = pattern.matcher(email).matches();
        if (!isOK) {
            return "请输入正确邮箱";
        }


        rabbitTemplate.convertAndSend("sendEmailExchange", "sendEmail", email);

        return "ok";
    }

    @RequestMapping("reg")
    public String reg(String username, String password, String repass, String tel, String email, String emailCode, Model model) {

        //校验用户名是否规范
        if (StringUtils.isEmpty(username)) {
            model.addAttribute("errorInfo", "用户名不能为空");
            return "userregister";
        }
        if (!username.matches("^[a-zA-Z]\\w{2,14}$")) {
            model.addAttribute("errorInfo", "用户名以字母开头，长度在3~15之间，只能包含字符、数字和下划线");
            return "userregister";
        }
        //校验密码是否规范
        if (StringUtils.isEmpty(password)) {
            model.addAttribute("errorInfo", "密码不能为空");
            return "userregister";
        }
        if (!password.matches("^[a-zA-Z]\\w{5,17}$")) {
            model.addAttribute("errorInfo", "密码以字母开头，长度在6~18之间，只能包含字符、数字和下划线");
            return "userregister";
        }
        //校验邮箱是否规范
        if (StringUtils.isEmpty(email)) {
            model.addAttribute("errorInfo", "邮箱Email不能为空");
            return "userregister";
        }
        if (!email.matches("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$")) {
            model.addAttribute("errorInfo", "邮箱Email格式不正确");
            return "userregister";
        }
        //校验电话是否规范
        if (StringUtils.isEmpty(tel)) {
            model.addAttribute("errorInfo", "电话不能为空");
            return "userregister";
        }
        if (!tel.matches("^1(3\\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\\d|9[0-35-9])\\d{8}$")) {
            model.addAttribute("errorInfo", "电话格式不正确");
            return "userregister";
        }
        //校验邮箱验证码
        String emailCodeRedis = stringRedisTemplate.opsForValue().get(email);
        if (StringUtils.isEmpty(emailCodeRedis) || !emailCodeRedis.equals(emailCode)) {
            model.addAttribute("errorInfo", "邮箱验证码错误");
            return "userregister";
        }

        //username.intern() 强制去字符串常量池里获取对象
        synchronized (username.intern()) {
            //校验用户名, 用户名要唯一
            if (StringUtils.isEmpty(username) || userService.getUserByUsername(username) != null) {
                model.addAttribute("errorInfo", "用户名已被占用,请重试");
                return "userregister";
            }

            //校验邮箱,邮箱要唯一
            if (StringUtils.isEmpty(email) || userService.getUserByEmail(email) != null) {
                model.addAttribute("errorInfo", "邮箱已被占用,请重试");
                return "userregister";
            }

            if (StringUtils.isEmpty(password) || StringUtils.isEmpty(repass) || !password.equals(repass)) {
                model.addAttribute("errorInfo", "请正确输入两次密码");
                return "userregister";
            }

            userService.reg(username, password, tel, email);
        }

        return "userlogin";
    }


    @RequestMapping("update")
    public String update(User user, MultipartFile source, Model model) {
        boolean flag = false;

        //username.intern() 强制去字符串常量池里获取对象
        synchronized (user.getUsername().intern()) {
            //校验用户名, 用户名要唯一
            if (userService.getUserByUsername(user.getUsername()) != null) {
                model.addAttribute("errorInfo", "用户名已被占用,请重试");
                return "usersetting";
            }

            //校验邮箱,邮箱要唯一
            if (userService.getUserByEmail(user.getEmail()) != null) {
                model.addAttribute("errorInfo", "邮箱已被占用,请重试");
                return "usersetting";
            }

            User userById = userService.getById(user.getId());
            if ("".equals(user.getUsername()) || user.getUsername() == null) {
                user.setUsername(userById.getUsername());
                flag = true;
            }
            if ("".equals(user.getPassword()) || user.getPassword() == null)
                user.setPassword(userById.getPassword());
            if ("".equals(user.getEmail()) || user.getEmail() == null)
                user.setEmail(userById.getEmail());
            if ("".equals(user.getTel()) || user.getTel() == null)
                user.setTel(userById.getTel());

            user.setUserPoints(userById.getUserPoints());

            if (source != null) {
                String originalFilename = source.getOriginalFilename();
                if (!originalFilename.equals("")) {
                String fileName = "http://localhost:10002/imgs/head/" + originalFilename;
                
//                控制如果不是图片就不让上传
//                String contentType = source.getContentType();
//            if (!"jpg".equals(contentType) || !"png".equals(contentType)) {
//                return "forward:/car/selectCarByT";
//            }

//                    获取到img这个目录的真实路径
                    String realPath = "F:\\image\\head"; // img/fileName
//                String read_img_path = realPath + "\\" + fileName;
                    String read_img_path = realPath + "\\" + originalFilename;

//                     使用multipart对象的方法保存文件
//                    上传的文件流保存在上面组合的指定路径下
                    try {
                        source.transferTo(new File(read_img_path));
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }

                    //保存图片的路径到数据
                    //设置图片路径到实体对象
                    user.setUserImg(fileName);
                }
            } else {
                user.setUserImg(userById.getUserImg());
            }
            userService.updateById(user);
        }
        if (flag)
            model.addAttribute("errorInfo", "ok");
        else {
            model.addAttribute("errorInfo", "toReLog");
            model.addAttribute("newName", user.getUsername());
        }
        return "usersetting";
    }

}

